﻿using System;
using System.Collections.Generic;
using System.Xml;
using System.Text;

using SharePointEnforcer.Utilities;

namespace SharePointEnforcer
{
    /// <summary>
    /// Represents the topmost config file, the one that includes the sites to crawl as well as their rule files. It is used to drive all of the other processing
    /// </summary>
    class RuleStarter
    {
        public RuleStarter(string pPathToRule)
        {
            Sites = new SiteRuleNodeCollection();

            string starterContent = EnforcerUtils.Files.LoadText(pPathToRule);
            if (string.IsNullOrEmpty(starterContent)) throw new EnforcerException(Resources.Enforcer.err_NoStarterFileFound, pPathToRule);

            XmlDocument doc = new XmlDocument();
            try
            {
                doc.LoadXml(starterContent);
            }
            catch (Exception ex)
            {
                throw new EnforcerException(ex, Resources.Enforcer.err_MalformedFileXml, pPathToRule, ex.Message);
            }

            // by now we have at least some XML

            XmlNodeList sites = doc.SelectNodes("/Sites/Site");
            if (sites == null || sites.Count < 1) throw new EnforcerException(Resources.Enforcer.err_StarterMustHaveSitesNode);

            // loop through the sites
            foreach (XmlNode site in sites)
            {
                Sites.Add(new SiteRuleNode(site));
            }
        }

        public SiteRuleNodeCollection Sites { get; protected set; }
    }

    class SiteRuleNodeCollection : List<SiteRuleNode> { }


    /// <summary>
    /// represents an individual entry in the starter file that defines what site to crawl and what rules to apply to that site
    /// </summary>
    class SiteRuleNode
    {
        public SiteRuleNode(XmlNode siteNode)
        {
            string siteUrl = EnforcerUtils.Xml.GetAttribute(siteNode, "url");
            if (string.IsNullOrEmpty(siteUrl)) throw new EnforcerException(Resources.Enforcer.err_StarterSiteMustHaveUrl);

            try
            {
                SiteUrl = new Uri(siteUrl);
            }
            catch (Exception ex)
            {
                throw new EnforcerException(ex, Resources.Enforcer.err_StarterSiteUrlBadFormat, siteUrl);
            }

            string ruleFile = EnforcerUtils.Xml.GetAttribute(siteNode, "rules"); ;
            XmlNodeList rules = siteNode.SelectNodes("Rules");

            // do we have rules?
            if (rules == null || rules.Count < 1 && string.IsNullOrEmpty(ruleFile)) throw new EnforcerException(Resources.Enforcer.err_StarterSiteMustHaveRules, siteUrl);

            // if we have a collection of rule nodes, get the path from the Xml
            if (rules.Count > 0)
            {
                RulePaths = new string[rules.Count];
                for (int i = 0; i < rules.Count; i++)
                {
                    RulePaths[i] = EnforcerUtils.Xml.GetAttribute(rules[i], "path");
                }
            }
            else
            {
                // the rule nodes may be in a delimited attribute instead.  Try to get them from there
                RulePaths = ruleFile.Split(EnforcerCommon.Constants.FileSplitCharacters, StringSplitOptions.RemoveEmptyEntries);
            }

            // now make sure the rule paths are valid
            foreach (string rulePath in RulePaths)
            {
                if (!EnforcerUtils.Files.Exists(rulePath))
                    throw new EnforcerException(Resources.Enforcer.err_StarterSiteRuleFileBadPath, rulePath, siteUrl);
            }
        }

        public Uri SiteUrl { get; protected set; }
        public string[] RulePaths { get; protected set; }
    }


}
